package adc.app.ui.wicket.valid;

import java.util.Collections;
import java.util.List;

import org.apache.wicket.model.IDetachable;
import org.apache.wicket.model.IModel;
import org.apache.wicket.util.lang.PropertyResolver;
import org.apache.wicket.validation.IValidatable;
import org.apache.wicket.validation.validator.AbstractValidator;

import adc.app.spec.IBo;
import adc.app.spec.IBoBs;
import adc.app.ui.wicket.model.SpringBeanModel;

public class DomainObjectPropertyUnicityValidator<T extends IBo, P> extends AbstractValidator<P> implements IDetachable {

	private static final long serialVersionUID = 1L;

	private final IModel<? extends IBoBs<T>> daoModel;
	private final String property;
	private final IModel<Long> idOtherThen;
	private final Class<T> domainClass;
	private String errorMessageKey;
	
	public <BS extends IBoBs<T>> DomainObjectPropertyUnicityValidator(Class<T> domainClass, Class<BS> bsClass, String property, IModel<Long> idOtherThen) {
		super();
		this.daoModel = new SpringBeanModel<BS>(bsClass);
		this.domainClass = domainClass;
		this.property = property;
		this.idOtherThen = idOtherThen;
	}
	
	public final String getProperty() {
		return property;
	}

	public final IModel<Long> getIdOtherThen() {
		return idOtherThen;
	}

	public final Class<T> getDomainClass() {
		return domainClass;
	}

	@Override
	protected void onValidate(IValidatable<P> validatable) {
		IBoBs<T> dao = daoModel.getObject();
		Object propertyValue = validatable.getValue();
        List<T> list = dao.list(Collections.singletonMap(property, propertyValue), null, null, null);
		Long id = idOtherThen == null ? null : idOtherThen.getObject();
		if (id == null && !list.isEmpty()) {
			this.error(validatable);
		}
		if (id != null) {
			for (T item : list) {
				Object value = PropertyResolver.getValue(property, item);
				if (propertyValue.equals(value) && !id.equals(item.getId())) {
					this.error(validatable);
				}
			}
		}
		daoModel.detach();
	}
	
	

	@Override
	public void detach() {
		daoModel.detach();
		idOtherThen.detach();
	}
	
	@Override
	protected String resourceKey() {
		return errorMessageKey != null ? errorMessageKey : super.resourceKey();
	}
	
	public final DomainObjectPropertyUnicityValidator<T, P> setResourceKey(String resourceKey) {
		errorMessageKey = resourceKey;
		return this;
	}
}
